@rebon/cli-darwin-arm64 1.8.7 → 1.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/bin/compose-runtime/payload/compose/shims/dsh-environment.js +34 -0
  2. package/bin/compose-runtime/src/commands-runtime.mjs +72 -0
  3. package/bin/compose-runtime/src/loader.mjs +7 -0
  4. package/bin/compose-runtime/src/probe.mjs +77 -0
  5. package/bin/compose-runtime/src/provided-modules.json +38 -0
  6. package/bin/compose-runtime/src/realm.mjs +5 -3
  7. package/bin/compose-runtime/src/registry.mjs +15 -2
  8. package/bin/compose-runtime/src/resolve.mjs +3 -33
  9. package/bin/marketplace/.claude-plugin/marketplace.json +258 -0
  10. package/bin/marketplace/plugins/dsh-llm-deepseek/LICENSE +21 -0
  11. package/bin/marketplace/plugins/dsh-llm-deepseek/llm-deepseek.js +672 -0
  12. package/bin/marketplace/plugins/dsh-llm-deepseek/rebon-plugin.json +27 -0
  13. package/bin/marketplace/plugins/dsh-tool-todo/LICENSE +21 -0
  14. package/bin/marketplace/plugins/dsh-tool-todo/rebon-plugin.json +27 -0
  15. package/bin/marketplace/plugins/dsh-tool-todo/tool-todo.js +143 -0
  16. package/bin/marketplace/plugins/dsh-tool-web/LICENSE +21 -0
  17. package/bin/marketplace/plugins/dsh-tool-web/rebon-plugin.json +27 -0
  18. package/bin/marketplace/plugins/dsh-tool-web/tool-web.js +1527 -0
  19. package/bin/marketplace/plugins/dsh-web-search-exa/LICENSE +21 -0
  20. package/bin/marketplace/plugins/dsh-web-search-exa/rebon-plugin.json +27 -0
  21. package/bin/marketplace/plugins/dsh-web-search-exa/web-search-exa.js +122 -0
  22. package/bin/mods-runtime/package.json +13 -0
  23. package/bin/mods-runtime/src/chain.mjs +188 -0
  24. package/bin/mods-runtime/src/classic.mjs +217 -0
  25. package/bin/mods-runtime/src/claude-code.mjs +101 -0
  26. package/bin/mods-runtime/src/client.mjs +316 -0
  27. package/bin/mods-runtime/src/engine.mjs +196 -0
  28. package/bin/mods-runtime/src/index.mjs +58 -0
  29. package/bin/mods-runtime/src/jsx-transform.mjs +324 -0
  30. package/bin/mods-runtime/src/mod.mjs +370 -0
  31. package/bin/mods-runtime/src/render.mjs +122 -0
  32. package/bin/mods-runtime/src/transpile.mjs +167 -0
  33. package/bin/plugin-host/src/cli.mjs +13 -0
  34. package/bin/plugin-host/src/host.mjs +11 -1
  35. package/bin/plugin-host/src/methods.mjs +4 -1
  36. package/bin/plugin-host/src/protocol.mjs +38 -4
  37. package/bin/rebon +2 -2
  38. package/bin/rebon-boa-helper +0 -0
  39. package/bin/rebon-browser-mcp +0 -0
  40. package/bin/rebon-computer-use +0 -0
  41. package/bin/rebon-lsp-mcp +0 -0
  42. package/bin/sandbox-win +0 -0
  43. package/package.json +1 -1
@@ -0,0 +1,34 @@
1
+ // Embedded-runtime shim of `@deepseek-ai/dsh-environment`, which DeepSeek
2
+ // Harness packages read their API keys and base URLs through
3
+ // (`environmentOf(ctx).get('EXA_API_KEY')`). The real package is not
4
+ // published, so a package installed from npm reaches this one.
5
+ //
6
+ // The embedded composition exposes no ambient environment (see
7
+ // dsh-launch-environment.js): a variable is visible only when the person
8
+ // granted it to this plugin's container at install, which the container
9
+ // announces in `REBON_GRANTED_ENV`. On the shared host nothing is granted,
10
+ // and every consumer takes its documented fallback — its own config, or the
11
+ // credentials seat.
12
+
13
+ const granted = new Set(
14
+ (process.env.REBON_GRANTED_ENV ?? '')
15
+ .split(',')
16
+ .map((name) => name.trim())
17
+ .filter(Boolean),
18
+ );
19
+
20
+ const SNAPSHOT = Object.freeze({
21
+ get(name) {
22
+ if (!granted.has(name)) return undefined;
23
+ const value = process.env[name];
24
+ return value === undefined ? undefined : Object.freeze({ name, value, source: 'container' });
25
+ },
26
+ has(name) {
27
+ return SNAPSHOT.get(name) !== undefined;
28
+ },
29
+ });
30
+
31
+ /** The environment a plugin may read: what its container was granted. */
32
+ export function environmentOf(_ctx) {
33
+ return SNAPSHOT;
34
+ }
@@ -0,0 +1,72 @@
1
+ // The `commands` seat: a DeepSeek Harness plugin's slash commands, as rebon's.
2
+ //
3
+ // `ctx.commands.register({ name, description, input, handler })` is the DSH
4
+ // command registry's call, unchanged. Each registration goes on the
5
+ // entry's sink as a command of kind `output`: running it asks the plugin
6
+ // (`command/invoke`), and what the handler returns is shown where the
7
+ // person typed it — a DSH command acts "without sending the command to the
8
+ // model", and rebon keeps it that way.
9
+ //
10
+ // The handler gets the invocation DSH defines: the text after the name, a
11
+ // signal, and the agent it ran for — here the session the command was typed
12
+ // in, by id, which is all a command handler outside DSH's own engine can be
13
+ // told about.
14
+ import { Service } from 'cordis';
15
+ import { sinkOf } from './registry.mjs';
16
+
17
+ const NAME = /^[a-z][a-z0-9-]*$/;
18
+
19
+ let sequence = 0;
20
+
21
+ /** A DSH `CommandResult` as the text rebon shows. */
22
+ function shown(result, name) {
23
+ if (typeof result === 'string') return result;
24
+ if (result && typeof result === 'object') {
25
+ if (result.kind === 'error') {
26
+ throw new Error(typeof result.text === 'string' && result.text ? result.text : `/${name} failed`);
27
+ }
28
+ return typeof result.text === 'string' ? result.text : '';
29
+ }
30
+ return '';
31
+ }
32
+
33
+ export default class RebonCommandsRuntime extends Service {
34
+ constructor(ctx) {
35
+ super(ctx, 'commands');
36
+ }
37
+
38
+ /// DSH's `CommandService.register`. Returns the disposer DSH promises; the
39
+ /// registration itself leaves with the entry, which is how rebon removes
40
+ /// every registration a plugin made.
41
+ register(definition) {
42
+ const name = definition?.name;
43
+ if (typeof name !== 'string' || !NAME.test(name)) {
44
+ throw new TypeError(`commands.register: ${JSON.stringify(name)} is not a lowercase command name`);
45
+ }
46
+ if (typeof definition.description !== 'string' || definition.description.length === 0) {
47
+ throw new TypeError(`commands.register: /${name} needs a description`);
48
+ }
49
+ if (typeof definition.handler !== 'function') {
50
+ throw new TypeError(`commands.register: /${name} needs a handler`);
51
+ }
52
+ const sink = sinkOf(this.ctx);
53
+ if (sink === undefined) {
54
+ throw new TypeError(`commands.register: /${name} was registered outside any plugin`);
55
+ }
56
+ const wire = { name, description: definition.description, kind: { type: 'output' } };
57
+ if (typeof definition.input?.hint === 'string' && definition.input.hint.length > 0) {
58
+ wire.hint = definition.input.hint;
59
+ }
60
+ sink.command(wire, async (request, callCtx) => {
61
+ const scope = callCtx?.scopeId ?? callCtx?.scope ?? 'rebon';
62
+ const result = await definition.handler({
63
+ commandId: `rebon-command-${++sequence}`,
64
+ agent: { id: scope, session: { id: scope } },
65
+ rawInput: typeof request?.rest === 'string' ? request.rest : '',
66
+ signal: callCtx?.signal ?? new AbortController().signal,
67
+ });
68
+ return shown(result, name);
69
+ });
70
+ return () => {};
71
+ }
72
+ }
@@ -21,6 +21,7 @@
21
21
  // one, and step 4 is last so the ambiguous case (a bare default function) goes
22
22
  // to the composition rather than being guessed at from argument counts.
23
23
  import { resolveEntry } from '../../plugin-host/src/loader.mjs';
24
+ import { createLoader as createModsLoader, isModRequest } from '../../mods-runtime/src/index.mjs';
24
25
 
25
26
  const own = (value, key) => value != null && Object.prototype.hasOwnProperty.call(value, key);
26
27
 
@@ -48,8 +49,13 @@ export function cordisPluginOf(module) {
48
49
  /// module does not recognise — an adapter that reimplemented it would be a
49
50
  /// second set of rules for the same shape.
50
51
  export async function createLoader({ next }) {
52
+ // A Claude Code mod is decided by the load request, before the module is
53
+ // read: rebon marked the request when it synthesised the mod's manifest,
54
+ // and the mods loader refuses to guess at one it did not mark.
55
+ const mods = await createModsLoader({ next });
51
56
  return {
52
57
  async load(request) {
58
+ if (isModRequest(request)) return mods.load(request);
53
59
  const url = resolveEntry(request.root, request.entry);
54
60
  let module;
55
61
  try {
@@ -71,6 +77,7 @@ export async function createLoader({ next }) {
71
77
  },
72
78
 
73
79
  async unload(pluginId) {
80
+ if (await mods.unload(pluginId)) return;
74
81
  const { disposeEntry } = await import('./realm.mjs');
75
82
  await disposeEntry(pluginId);
76
83
  },
@@ -0,0 +1,77 @@
1
+ // Mounts one Cordis plugin package on a realm of its own and says what it
2
+ // registered, or why it could not mount.
3
+ //
4
+ // node --permission --allow-fs-read=... probe.mjs <package root> <entry> [config JSON]
5
+ //
6
+ // This is how rebon reads a DeepSeek Harness package published to npm, which
7
+ // carries no rebon manifest: the package is mounted against rebon's own
8
+ // seats with a sink that admits every name and records it, and what it
9
+ // recorded becomes the ceiling a person approves at install. A package that
10
+ // needs a service rebon does not offer fails here with that service's name —
11
+ // which is the compatibility answer, given before anything is installed.
12
+ //
13
+ // The caller runs it under Node's permission model (the package and this
14
+ // runtime readable, nothing writable, no processes): the package is someone
15
+ // else's code, executing for the first time.
16
+ //
17
+ // One line of JSON on stdout, whatever happens.
18
+ import path from 'node:path';
19
+ import { pathToFileURL } from 'node:url';
20
+ import { installModuleResolution } from './resolve.mjs';
21
+
22
+ function injects(plugin) {
23
+ const inject = plugin?.inject;
24
+ if (Array.isArray(inject)) return { required: inject, optional: [] };
25
+ if (inject && typeof inject === 'object') {
26
+ return { required: inject.required ?? [], optional: inject.optional ?? [] };
27
+ }
28
+ return { required: [], optional: [] };
29
+ }
30
+
31
+ async function probe(root, entry, config) {
32
+ installModuleResolution();
33
+ const { cordisPluginOf } = await import('./loader.mjs');
34
+ const { createRealm, mountEntry, builtinSeats } = await import('./realm.mjs');
35
+ let module;
36
+ try {
37
+ module = await import(pathToFileURL(path.resolve(root, entry)).href);
38
+ } catch (cause) {
39
+ return { ok: false, code: '[ENTRY_FAILED]', error: String(cause?.message ?? cause) };
40
+ }
41
+ const plugin = cordisPluginOf(module);
42
+ if (plugin === undefined) {
43
+ return { ok: false, code: '[NOT_CORDIS]', error: `${entry} exports no Cordis plugin (no apply)` };
44
+ }
45
+ const wanted = injects(plugin);
46
+ await createRealm({});
47
+ const seats = builtinSeats();
48
+ const missing = wanted.required.filter((service) => !seats.includes(service));
49
+ const base = { name: plugin.name ?? null, inject: wanted, seats };
50
+ try {
51
+ const sink = await mountEntry({ pluginId: 'probe', config }, plugin, { probe: true });
52
+ const loaded = sink.loaded();
53
+ return {
54
+ ok: true,
55
+ ...base,
56
+ tools: loaded.tools.map((tool) => ({ name: tool.name, description: tool.description ?? '' })),
57
+ services: loaded.services,
58
+ llmProviders: loaded.llmProviders,
59
+ eventTopics: loaded.eventTopics,
60
+ commands: loaded.commands.map((command) => ({ name: command.name, description: command.description })),
61
+ report: sink.report(),
62
+ };
63
+ } catch (cause) {
64
+ return { ok: false, ...base, missing, code: cause?.code ?? '[ACTIVATE_FAILED]', error: String(cause?.message ?? cause) };
65
+ }
66
+ }
67
+
68
+ if (import.meta.url === pathToFileURL(process.argv[1]).href) {
69
+ const [root, entry, config] = process.argv.slice(2);
70
+ let answer;
71
+ try {
72
+ answer = await probe(root, entry, config ? JSON.parse(config) : null);
73
+ } catch (cause) {
74
+ answer = { ok: false, code: '[PROBE_FAILED]', error: String(cause?.message ?? cause) };
75
+ }
76
+ process.stdout.write(`${JSON.stringify(answer)}\n`, () => process.exit(0));
77
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "note": "The bare specifiers the composition answers itself, and from where. `payload` entries are relative to the payload directory, `runtime` entries to this package's src/. Read by src/resolve.mjs and by rebon's installer, which installs from npm only the peers of a package that are not here.",
3
+ "payload": {
4
+ "cordis": "vendor/cordis/index.js",
5
+ "cosmokit": "vendor/cosmokit/index.mjs",
6
+ "schemastery": "vendor/schemastery/index.mjs",
7
+ "@deepseek-ai/cordis": "vendor/cordis/index.js",
8
+ "@deepseek-ai/cosmokit": "vendor/cosmokit/index.mjs",
9
+ "@deepseek-ai/schemastery": "vendor/schemastery/index.mjs",
10
+ "@deepseek-ai/cordis-plugin-timer": "vendor/dsh/timer.js",
11
+ "@deepseek-ai/cordis-plugin-logger-console": "vendor/dsh/logger-console.js",
12
+ "@deepseek-ai/dsh-llm-deepseek": "vendor/dsh/llm-deepseek.js",
13
+ "@deepseek-ai/dsh-timeout": "vendor/dsh/timeout.js",
14
+ "@deepseek-ai/dsh-llm": "compose/shims/dsh-llm.js",
15
+ "@deepseek-ai/dsh-credentials": "compose/shims/dsh-credentials.js",
16
+ "@deepseek-ai/dsh-settings": "compose/shims/dsh-settings.js",
17
+ "@deepseek-ai/dsh-launch-environment": "compose/shims/dsh-launch-environment.js",
18
+ "@deepseek-ai/dsh-anonymous-user-id": "compose/shims/dsh-anonymous-user-id.js",
19
+ "eventsource-parser": "vendor/eventsource-parser/index.js",
20
+ "@deepseek-ai/dsh-tools": "compose/shims/dsh-tools.js",
21
+ "@deepseek-ai/dsh-tool-todo": "vendor/dsh/tool-todo.js",
22
+ "zod": "compose/shims/zod-lite.js",
23
+ "@deepseek-ai/dsh-web": "compose/shims/dsh-web.js",
24
+ "@deepseek-ai/dsh-web-search-exa": "vendor/dsh/web-search-exa.js",
25
+ "@deepseek-ai/dsh-tool-web": "vendor/dsh/tool-web.js",
26
+ "@deepseek-ai/dsh-scope": "vendor/dsh/scope.js",
27
+ "@deepseek-ai/dsh-session": "vendor/dsh/session.js",
28
+ "@deepseek-ai/dsh-agent": "vendor/dsh/agent.js",
29
+ "@deepseek-ai/dsh-system-prompt": "vendor/dsh/system-prompt.js",
30
+ "@deepseek-ai/dsh-agent-loop": "vendor/dsh/agent-loop.js",
31
+ "@deepseek-ai/dsh-environment": "compose/shims/dsh-environment.js",
32
+ "@deepseek-ai/dsh-user-id": "compose/shims/dsh-anonymous-user-id.js"
33
+ },
34
+ "runtime": {
35
+ "rebon": "./bridge.mjs",
36
+ "eventsource-parser/stream": "./eventsource-stream.mjs"
37
+ }
38
+ }
@@ -27,10 +27,11 @@ import RebonCredentials from './credentials-runtime.mjs';
27
27
  import RebonToolsRuntime from './tools-runtime.mjs';
28
28
  import RebonWebRuntime from './web-runtime.mjs';
29
29
  import RebonSystemPromptRuntime from './systemprompt-runtime.mjs';
30
+ import RebonCommandsRuntime from './commands-runtime.mjs';
30
31
 
31
32
  /** The built-in seats, in mount order: a dsh `inject` is satisfied at mount
32
33
  * time, so a seat that arrives after the plugin needing it never arrives. */
33
- const BUILTIN_SEATS = ['llm', 'credentials', 'tools', 'web', 'systemPrompt'];
34
+ const BUILTIN_SEATS = ['llm', 'credentials', 'tools', 'web', 'systemPrompt', 'commands'];
34
35
 
35
36
  let state;
36
37
 
@@ -104,6 +105,7 @@ export async function createRealm({ web = null, entries = [] } = {}) {
104
105
  await ctx.plugin(RebonToolsRuntime);
105
106
  await ctx.plugin(RebonWebRuntime, { web });
106
107
  await ctx.plugin(RebonSystemPromptRuntime);
108
+ await ctx.plugin(RebonCommandsRuntime);
107
109
 
108
110
  state = { ctx, placements, groups, realms, fibers: new Map(), sinks: new Map() };
109
111
  return state;
@@ -148,7 +150,7 @@ function requiredInjects(plugin) {
148
150
  /// The sink rides on the entry's own derived context, which is what lets a seat
149
151
  /// attribute a registration synchronously — the moment a plugin registers, the
150
152
  /// context it registered through says which plugin it was.
151
- export async function mountEntry(request, plugin) {
153
+ export async function mountEntry(request, plugin, { probe = false } = {}) {
152
154
  const live = realm();
153
155
  const { pluginId } = request;
154
156
  if (live.groups.has(pluginId)) {
@@ -161,7 +163,7 @@ export async function mountEntry(request, plugin) {
161
163
  throw new ComposeError('[PLUGIN_ALREADY_LOADED]', `${pluginId} is already mounted`);
162
164
  }
163
165
  const parent = live.placements.get(pluginId) ?? live.ctx;
164
- const sink = new RegistrationSink(pluginId, request);
166
+ const sink = new RegistrationSink(pluginId, request, { probe });
165
167
  const derived = parent.extend({ [OWNER]: pluginId, [SINK]: sink });
166
168
  // Refused before mounting rather than waited for. Cordis lets a plugin wait
167
169
  // for a service that has not arrived yet, and inside one composition that is
@@ -37,19 +37,25 @@ class RegistrationError extends Error {
37
37
  export class RegistrationSink {
38
38
  #sealed = false;
39
39
 
40
- constructor(pluginId, declared = {}) {
40
+ /// `probe` admits every name and records it: how rebon learns what a
41
+ /// package it has never seen registers, so its ceiling can be written for
42
+ /// a person to approve. Never used for a load that serves anything.
43
+ constructor(pluginId, declared = {}, { probe = false } = {}) {
41
44
  this.pluginId = pluginId;
45
+ this.probe = probe;
42
46
  this.declared = {
43
47
  services: new Set(declared.services ?? []),
44
48
  eventTopics: new Set(declared.eventTopics ?? []),
45
49
  llmProviders: new Set(declared.llmProviders ?? []),
46
50
  tools: new Set(declared.tools ?? []),
51
+ commands: new Set(declared.commands ?? []),
47
52
  };
48
53
  /** Protocol-shaped registrations, answered by `plugin/load`. */
49
54
  this.services = new Map();
50
55
  this.topics = new Map();
51
56
  this.llmProviders = new Map();
52
57
  this.tools = new Map();
58
+ this.commands = new Map();
53
59
  /** Handles on a session, handed out when a scope opens. */
54
60
  this.scopeHandlers = [];
55
61
  /** The sessions this plugin is currently attached to.
@@ -81,7 +87,7 @@ export class RegistrationSink {
81
87
  if (typeof name !== 'string' || name.length === 0) {
82
88
  throw new RegistrationError('[WRONG_SHAPE]', `a ${kind} needs a non-empty name`);
83
89
  }
84
- if (!declared.has(name)) {
90
+ if (!this.probe && !declared.has(name)) {
85
91
  throw new RegistrationError(
86
92
  '[UNAUTHORIZED_REGISTER]',
87
93
  `${kind} ${JSON.stringify(name)} is not declared by ${this.pluginId}'s manifest`,
@@ -113,6 +119,11 @@ export class RegistrationSink {
113
119
  ///
114
120
  /// Not declared, because it is not a capability: every power the handle
115
121
  /// carries is one of the declarations above, checked when it is used.
122
+ command(definition, handler) {
123
+ this.#admit('command', definition?.name, this.declared.commands);
124
+ this.commands.set(definition.name, { definition, handler });
125
+ }
126
+
116
127
  scope(handler) {
117
128
  if (typeof handler !== 'function') {
118
129
  throw new RegistrationError('[WRONG_SHAPE]', 'a scope handler must be a function');
@@ -156,6 +167,8 @@ export class RegistrationSink {
156
167
  topicHandlers: this.topics,
157
168
  llmAdapters: this.llmProviders,
158
169
  toolHandlers: new Map([...this.tools].map(([name, entry]) => [name, entry.handler])),
170
+ commands: [...this.commands.values()].map((entry) => entry.definition),
171
+ commandHandlers: new Map([...this.commands].map(([name, entry]) => [name, entry.handler])),
159
172
  scopeHandlers: [...this.scopeHandlers],
160
173
  };
161
174
  }
@@ -24,50 +24,20 @@ import { registerHooks } from 'node:module';
24
24
  import path from 'node:path';
25
25
  import { pathToFileURL } from 'node:url';
26
26
  import { payloadDir } from './payload.mjs';
27
+ import provided from './provided-modules.json' with { type: 'json' };
27
28
 
28
29
  /// Payload-relative module map, keyed by bare specifier.
29
30
  ///
30
31
  /// Mirrors `build_import_map` entry for entry, minus the `node:` shims.
31
32
  export function payloadModules(dir) {
32
33
  const at = (relative) => pathToFileURL(path.join(dir, relative)).href;
33
- return new Map(Object.entries({
34
- cordis: at('vendor/cordis/index.js'),
35
- cosmokit: at('vendor/cosmokit/index.mjs'),
36
- schemastery: at('vendor/schemastery/index.mjs'),
37
- '@deepseek-ai/cordis': at('vendor/cordis/index.js'),
38
- '@deepseek-ai/cosmokit': at('vendor/cosmokit/index.mjs'),
39
- '@deepseek-ai/schemastery': at('vendor/schemastery/index.mjs'),
40
- '@deepseek-ai/cordis-plugin-timer': at('vendor/dsh/timer.js'),
41
- '@deepseek-ai/cordis-plugin-logger-console': at('vendor/dsh/logger-console.js'),
42
- '@deepseek-ai/dsh-llm-deepseek': at('vendor/dsh/llm-deepseek.js'),
43
- '@deepseek-ai/dsh-timeout': at('vendor/dsh/timeout.js'),
44
- '@deepseek-ai/dsh-llm': at('compose/shims/dsh-llm.js'),
45
- '@deepseek-ai/dsh-credentials': at('compose/shims/dsh-credentials.js'),
46
- '@deepseek-ai/dsh-settings': at('compose/shims/dsh-settings.js'),
47
- '@deepseek-ai/dsh-launch-environment': at('compose/shims/dsh-launch-environment.js'),
48
- '@deepseek-ai/dsh-anonymous-user-id': at('compose/shims/dsh-anonymous-user-id.js'),
49
- 'eventsource-parser': at('vendor/eventsource-parser/index.js'),
50
- '@deepseek-ai/dsh-tools': at('compose/shims/dsh-tools.js'),
51
- '@deepseek-ai/dsh-tool-todo': at('vendor/dsh/tool-todo.js'),
52
- zod: at('compose/shims/zod-lite.js'),
53
- '@deepseek-ai/dsh-web': at('compose/shims/dsh-web.js'),
54
- '@deepseek-ai/dsh-web-search-exa': at('vendor/dsh/web-search-exa.js'),
55
- '@deepseek-ai/dsh-tool-web': at('vendor/dsh/tool-web.js'),
56
- '@deepseek-ai/dsh-scope': at('vendor/dsh/scope.js'),
57
- '@deepseek-ai/dsh-session': at('vendor/dsh/session.js'),
58
- '@deepseek-ai/dsh-agent': at('vendor/dsh/agent.js'),
59
- '@deepseek-ai/dsh-system-prompt': at('vendor/dsh/system-prompt.js'),
60
- '@deepseek-ai/dsh-agent-loop': at('vendor/dsh/agent-loop.js'),
61
- }));
34
+ return new Map(Object.entries(provided.payload).map(([name, relative]) => [name, at(relative)]));
62
35
  }
63
36
 
64
37
  /// Specifiers this package answers itself rather than from the payload.
65
38
  export function localModules() {
66
39
  const at = (relative) => new URL(relative, import.meta.url).href;
67
- return new Map(Object.entries({
68
- rebon: at('./bridge.mjs'),
69
- 'eventsource-parser/stream': at('./eventsource-stream.mjs'),
70
- }));
40
+ return new Map(Object.entries(provided.runtime).map(([name, relative]) => [name, at(relative)]));
71
41
  }
72
42
 
73
43
  let installed;
@@ -0,0 +1,258 @@
1
+ {
2
+ "name": "rebon",
3
+ "owner": {
4
+ "name": "Rebon",
5
+ "url": "https://github.com/RebonAI/Rebon-Code"
6
+ },
7
+ "description": "Rebon's own marketplace: DeepSeek Harness plugins and Claude Code mods.",
8
+ "metadata": {
9
+ "version": "1"
10
+ },
11
+ "plugins": [
12
+ {
13
+ "name": "dsh-tool-todo",
14
+ "source": "./plugins/dsh-tool-todo",
15
+ "description": "DeepSeek Harness todo list: a todo_write tool the model keeps its plan in.",
16
+ "version": "0.1.0",
17
+ "category": "deepseek-harness",
18
+ "tags": [
19
+ "dsh",
20
+ "deepseek"
21
+ ]
22
+ },
23
+ {
24
+ "name": "dsh-tool-web",
25
+ "source": "./plugins/dsh-tool-web",
26
+ "description": "DeepSeek Harness web tools: web_search and web_fetch.",
27
+ "version": "0.1.0",
28
+ "category": "deepseek-harness",
29
+ "tags": [
30
+ "dsh",
31
+ "deepseek"
32
+ ]
33
+ },
34
+ {
35
+ "name": "dsh-web-search-exa",
36
+ "source": "./plugins/dsh-web-search-exa",
37
+ "description": "DeepSeek Harness Exa search backend for web_search (needs an Exa API key).",
38
+ "version": "0.1.0",
39
+ "category": "deepseek-harness",
40
+ "tags": [
41
+ "dsh",
42
+ "deepseek"
43
+ ]
44
+ },
45
+ {
46
+ "name": "dsh-llm-deepseek",
47
+ "source": "./plugins/dsh-llm-deepseek",
48
+ "description": "DeepSeek Harness model provider for the official DeepSeek API, on the plugin plane.",
49
+ "version": "0.1.0",
50
+ "category": "deepseek-harness",
51
+ "tags": [
52
+ "dsh",
53
+ "deepseek"
54
+ ]
55
+ },
56
+ {
57
+ "name": "dsh-web-search-perplexity",
58
+ "source": {
59
+ "source": "npm",
60
+ "package": "@deepseek-ai/dsh-web-search-perplexity",
61
+ "version": "0.0.1-rc.1"
62
+ },
63
+ "description": "DeepSeek Harness Perplexity search backend for web_search (needs a Perplexity API key).",
64
+ "version": "0.0.1-rc.1",
65
+ "category": "deepseek-harness",
66
+ "tags": [
67
+ "dsh",
68
+ "deepseek",
69
+ "npm"
70
+ ]
71
+ },
72
+ {
73
+ "name": "dsh-web-search-deepseek",
74
+ "source": {
75
+ "source": "npm",
76
+ "package": "@deepseek-ai/dsh-web-search-deepseek",
77
+ "version": "0.0.1-rc.1"
78
+ },
79
+ "description": "DeepSeek Harness DeepSeek search backend for web_search, through the official API.",
80
+ "version": "0.0.1-rc.1",
81
+ "category": "deepseek-harness",
82
+ "tags": [
83
+ "dsh",
84
+ "deepseek",
85
+ "npm"
86
+ ]
87
+ },
88
+ {
89
+ "name": "dsh-web-fetch-http",
90
+ "source": {
91
+ "source": "npm",
92
+ "package": "@deepseek-ai/dsh-web-fetch-http",
93
+ "version": "0.0.1-rc.5"
94
+ },
95
+ "description": "DeepSeek Harness public HTTP(S) fetch provider for web_fetch.",
96
+ "version": "0.0.1-rc.5",
97
+ "category": "deepseek-harness",
98
+ "tags": [
99
+ "dsh",
100
+ "deepseek",
101
+ "npm"
102
+ ]
103
+ },
104
+ {
105
+ "name": "dsh-tool-call-timeout-policy",
106
+ "source": {
107
+ "source": "npm",
108
+ "package": "@deepseek-ai/dsh-tool-call-timeout-policy",
109
+ "version": "0.0.1-rc.3"
110
+ },
111
+ "description": "DeepSeek Harness per-tool deadline: a tool call that outlives it answers TOOL_TIMEOUT.",
112
+ "version": "0.0.1-rc.3",
113
+ "category": "deepseek-harness",
114
+ "tags": [
115
+ "dsh",
116
+ "deepseek",
117
+ "npm"
118
+ ]
119
+ },
120
+ {
121
+ "name": "dsh-repeat-tool-reminder",
122
+ "source": {
123
+ "source": "npm",
124
+ "package": "@deepseek-ai/dsh-repeat-tool-reminder",
125
+ "version": "0.0.1-rc.3"
126
+ },
127
+ "description": "DeepSeek Harness reminder when the agent loops on identical tool calls.",
128
+ "version": "0.0.1-rc.3",
129
+ "category": "deepseek-harness",
130
+ "tags": [
131
+ "dsh",
132
+ "deepseek",
133
+ "npm"
134
+ ]
135
+ },
136
+ {
137
+ "name": "dsh-skill-office",
138
+ "source": {
139
+ "source": "npm",
140
+ "package": "@deepseek-ai/dsh-skill-office",
141
+ "version": "0.1.6-alpha.2"
142
+ },
143
+ "description": "DeepSeek Harness skills for Word, Excel and PowerPoint documents, as rebon skills.",
144
+ "version": "0.1.6-alpha.2",
145
+ "category": "deepseek-harness",
146
+ "tags": [
147
+ "dsh",
148
+ "deepseek",
149
+ "npm"
150
+ ]
151
+ },
152
+ {
153
+ "name": "agent-radar",
154
+ "source": {
155
+ "source": "git-subdir",
156
+ "url": "hamzafer/claude-code-mods",
157
+ "path": "mods/agent-radar"
158
+ },
159
+ "description": "One live line above the prompt per running subagent; /radar shows every agent and its messages.",
160
+ "category": "claude-code-mods",
161
+ "tags": [
162
+ "mod",
163
+ "community"
164
+ ],
165
+ "homepage": "https://github.com/hamzafer/claude-code-mods"
166
+ },
167
+ {
168
+ "name": "context-bar",
169
+ "source": {
170
+ "source": "git-subdir",
171
+ "url": "hamzafer/claude-code-mods",
172
+ "path": "mods/context-bar"
173
+ },
174
+ "description": "Your context window as a stacked bar above the prompt; /context-bar shows or hides it.",
175
+ "category": "claude-code-mods",
176
+ "tags": [
177
+ "mod",
178
+ "community"
179
+ ],
180
+ "homepage": "https://github.com/hamzafer/claude-code-mods"
181
+ },
182
+ {
183
+ "name": "snake",
184
+ "source": {
185
+ "source": "git-subdir",
186
+ "url": "hamzafer/claude-code-mods",
187
+ "path": "mods/snake"
188
+ },
189
+ "description": "Play Snake in a pane while Claude works; /snake turns it on or off.",
190
+ "category": "claude-code-mods",
191
+ "tags": [
192
+ "mod",
193
+ "community"
194
+ ],
195
+ "homepage": "https://github.com/hamzafer/claude-code-mods"
196
+ },
197
+ {
198
+ "name": "next-steps",
199
+ "source": {
200
+ "source": "git-subdir",
201
+ "url": "hamzafer/claude-code-mods",
202
+ "path": "mods/next-steps"
203
+ },
204
+ "description": "Suggested next steps drawn above the prompt after each answer.",
205
+ "category": "claude-code-mods",
206
+ "tags": [
207
+ "mod",
208
+ "community"
209
+ ],
210
+ "homepage": "https://github.com/hamzafer/claude-code-mods"
211
+ },
212
+ {
213
+ "name": "session-status",
214
+ "source": {
215
+ "source": "git-subdir",
216
+ "url": "liawzishen/claude-code-mods",
217
+ "path": "session-status"
218
+ },
219
+ "description": "Elapsed time, prompts and tool calls in the status line.",
220
+ "category": "claude-code-mods",
221
+ "tags": [
222
+ "mod",
223
+ "community"
224
+ ],
225
+ "homepage": "https://github.com/liawzishen/claude-code-mods"
226
+ },
227
+ {
228
+ "name": "git-diff-timeline",
229
+ "source": {
230
+ "source": "git-subdir",
231
+ "url": "liawzishen/claude-code-mods",
232
+ "path": "git-diff-timeline"
233
+ },
234
+ "description": "A Git Diff pane: what changed, file by file, with branch compare; /gitdiff opens it.",
235
+ "category": "claude-code-mods",
236
+ "tags": [
237
+ "mod",
238
+ "community"
239
+ ],
240
+ "homepage": "https://github.com/liawzishen/claude-code-mods"
241
+ },
242
+ {
243
+ "name": "token-weather",
244
+ "source": {
245
+ "source": "git-subdir",
246
+ "url": "cskwork/claude-code-mods",
247
+ "path": "token-weather"
248
+ },
249
+ "description": "A live forecast of the context window, drawn above the prompt.",
250
+ "category": "claude-code-mods",
251
+ "tags": [
252
+ "mod",
253
+ "community"
254
+ ],
255
+ "homepage": "https://github.com/cskwork/claude-code-mods"
256
+ }
257
+ ]
258
+ }